package com.qm.console.controller.rest;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.qm.console.controller.dto.BaseDO;
import com.qm.console.controller.dto.BaseRsp;
import com.qm.console.controller.dto.ResultEnum;
import com.qm.console.dao.model.*;
import com.qm.console.excel.ExportExcel;
import com.qm.console.excel.PercentField;
import com.qm.console.excel.UnitField;
import com.qm.console.pubdef.dto.analysis.*;
import com.qm.console.pubdef.dto.anchor.ImMsgQueryDTO;
import com.qm.console.pubdef.dto.anchor.TurnSignUpDTO;
import com.qm.console.pubdef.dto.user.PageInfoDTO;
import com.qm.console.pubdef.dto.user.VideoVoiceListDTO;
import com.qm.console.pubdef.dto.analysis.ChannelQueryDTO;
import com.qm.console.pubdef.dto.analysis.PropQueryDTO;
import com.qm.console.pubdef.dto.analysis.liftingRecordDTO;
import com.qm.console.pubdef.dto.analysis.onlineQueryDTO;
import com.qm.console.service.analysis.AnalysisService;
import com.qm.console.utils.PageUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.qm.console.utils.EmojiConverterUtil.emojiConvert;

/**
 * //                       _oo0oo_
 * //                      o8888888o
 * //                      88" . "88
 * //                      (| -_- |)
 * //                      0\  =  /0
 * //                    ___/`---'\___
 * //                  .' \\|     |// '.
 * //                 / \\|||  :  |||// \
 * //                / _||||| -:- |||||- \
 * //               |   | \\\  -  /// |   |
 * //               | \_|  ''\---/''  |_/ |
 * //               \  .-\__  '-'  ___/-. /
 * //             ___'. .'  /--.--\  `. .'___
 * //          ."" '<  `.___\_<|>_/___.' >' "".
 * //         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 * //         \  \ `_.   \_ __\ /__ _/   .-` /  /
 * //     =====`-.____`.___ \_____/___.-`___.-'=====
 * //                       `=---='
 * //
 * //
 * //     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * //
 * //               佛祖保佑         永无BUG
 * <p>
 * com.qm.console.controller.rest
 * Created on 2020/7/7.
 */
@RestController
@RequestMapping("/analysis")
public class AnalysisController {

    @Autowired
    private AnalysisService analysisService;

    @GetMapping("channels")
    public BaseRsp getChannels() {
        return new BaseRsp(ResultEnum.SUCCESS, analysisService.getChannels());
    }

    @GetMapping("versions")
    public BaseRsp getVersions() {
        return new BaseRsp(ResultEnum.SUCCESS, analysisService.getVersions());
    }

    @GetMapping("appNames")
    public BaseRsp getAppNames() {
        return new BaseRsp(ResultEnum.SUCCESS, analysisService.getAppNames());
    }

    @GetMapping("home")
    @ExportExcel(itemCls = BasicStatisticsDO.class,
            unitFields = {@UnitField(unit = 100, key = "totalRecharge"), @UnitField(key="totalWithdraw", unit = 100)},
            percentFields = {@PercentField(dest = "remain1Day", numerator = "remain1Day", denominator = "activateCount")}
            )
    public BaseRsp getHome(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.basicCount(query),
                "list", analysisService.basics(query)));
    }

    @GetMapping("overview")
    @ExportExcel(itemCls = overviewStatisticsDO.class,
            unitFields = {@UnitField(unit = 100, key = "totalRecharge"), @UnitField(key="totalWithdraw", unit = 100)},
            percentFields = {@PercentField(dest = "remain1Day", numerator = "remain1Day", denominator = "activateCount")}
    )
    public BaseRsp getoverview(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.overviewCount(query),
                "abTests", analysisService.overvieTests(),
                "list", analysisService.overview(query)));
    }

    @GetMapping("lifting/record")
    public BaseRsp liftingRecord(liftingRecordDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.liftingRecordCount(query),
                "list", analysisService.liftingRecordList(query)));
    }

    @GetMapping("active/user")
    public BaseRsp activeUser(LossRetainedDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.activeUserCount(query),
                "abTests", analysisService.getlossRetainedTests(),
                "list", analysisService.activeUserList(query)));
    }

    @GetMapping("ToWashAway/user")
    public BaseRsp washAwayUser(LossRetainedDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.WashAwayCount(query),
                "abTests", analysisService.getlossRetainedTests(),
                "list", analysisService.WashAwayList(query)));
    }

    @GetMapping("activate")
    public BaseRsp getActivates(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.activateCount(query),
                "list", analysisService.activates(query)));
    }

    @GetMapping("chat")
    public BaseRsp getChats(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.chatCount(query),
                "list", analysisService.chats(query)));
    }

    @GetMapping("division")
    public BaseRsp getDivisions(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.divisionCount(query),
                "list", analysisService.divisions(query)));
    }

    @GetMapping("recharge")
    public BaseRsp getRecharges(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.rechargeCount(query),
                "list", analysisService.recharges(query)));
    }

    @GetMapping("recharge/Analysis")
    public BaseRsp getRechargesAnalysis(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.rechargeAnalysisCount(query),
                "list", analysisService.rechargeAnalysisList(query)));
    }

    @GetMapping("user/recharge")
    public BaseRsp getUserRecharge(ChannelQueryDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.userRechargeCount(query),
                "list", analysisService.userRecharges(query)));
    }

    @GetMapping("promotion/costs")
    public BaseRsp getPromotionCosts(ChannelQueryDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.PromotionCostsCount(query),
                "list", analysisService.PromotionCostsList(query)));
    }

    @GetMapping("profit")
    public BaseRsp getUserProfits(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.userProfitCount(query),
                "list", analysisService.userProfits(query)));
    }

    @GetMapping("withdraw")
    public BaseRsp getWithdraws(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.withdrawCount(query),
                "list", analysisService.withdraws(query)));
    }

    @GetMapping("diamond")
    public BaseRsp getDiamondStatistics(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("count", analysisService.diamondStatisticsCount(query),
                "list", analysisService.diamondStatistics(query)));
    }

    /*
    道具产销
     */
    @GetMapping("/prop/diamond")
    public BaseRsp getDiamond(PropQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.diamondTotal(query),
                "list", analysisService.diamondList(query),
                "abTests", analysisService.getDiamondAbTests(),
                "inventory", analysisService.diamondInventoryList(query),
                "active", analysisService.diamondActiveList(query)
        ));
    }

    @GetMapping("/prop/score")
    public BaseRsp getScore(PropQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.scoreTotal(query),
                "list", analysisService.scoreList(query),
                "abTests", analysisService.getScoreAbTests(),
                "inventory", analysisService.scoreInventoryList(query),
                "active", analysisService.scoreActiveList(query)
        ));
    }

    @GetMapping("/prop/card")
    public BaseRsp getCard(PropQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.cardTotal(query),
                "list", analysisService.cardList(query),
                "abTests", analysisService.getCardAbTests(),
                "inventory", analysisService.cardInventoryList(query),
                "active", analysisService.cardActiveList(query)
        ));
    }

    @GetMapping("/prop/ticket")
    public BaseRsp getTicket(PropQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.ticketTotal(query),
                "list", analysisService.ticketList(query),
                "abTests", analysisService.getTicketAbTests(),
                "inventory", analysisService.ticketInventoryList(query),
                "active", analysisService.ticketActiveList(query)
        ));
    }

    @GetMapping("/prop/voiceCard")
    public BaseRsp getVoiceCard(PropQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.voiceCardTotal(query),
                "list", analysisService.voiceCardList(query),
                "abTests", analysisService.getVoiceCardAbTests(),
                "inventory", analysisService.voiceCardInventoryList(query),
                "active", analysisService.voiceCardActiveList(query)
        ));
    }
    /* */

    @GetMapping("/luckyCard/list")
    public BaseRsp luckyCardList(ActivityDO query) {
        List<Map> list = analysisService.luckyCardList(query);
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", list.size(),
                "list", list,
                "pool", analysisService.luckyCardPoolList(query)
        ));
    }

    @GetMapping("/luckyGift/list")
    public BaseRsp luckyGiftList(ActivityDO query) {
        List<Map> list = analysisService.luckyGiftList(query);
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", list.size(),
                "list", list,
                "pool", analysisService.luckyGiftPoolList(query)
        ));
    }

    @GetMapping("/abnormity/warning")
    public BaseRsp abnormityWarning(ChannelQueryDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.AbnormityWarningCount(query),
                "list", analysisService.getAbnormityWarning(query)
        ));
    }

    @GetMapping("/liveChat")
    public BaseRsp LiveChat(ImMsgQueryDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.liveChatCount(query),
                "list", analysisService.liveChat(query)
        ));
    }

    @GetMapping("/liveChat/detail")
    public BaseRsp liveChatDetail(ImMsgQueryDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.liveChatDetailCount(query),
                "list", analysisService.liveChatDetail(query)
        ));
    }

    @GetMapping("/online/User")
    public BaseRsp onlineUser(onlineQueryDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "count", analysisService.onlineUserCount(query),
                "list", analysisService.onlineUser(query)
        ));
    }

    @GetMapping("/online/History")
    public BaseRsp onlineHistory(onlineQueryDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.onlineHistory(query)
        ));
    }

    @GetMapping("/realTime/list")
    public BaseRsp realTimeList(VideoVoiceListDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.realTimeList(query)
        ));
    }

    @GetMapping("/realTime/history")
    public BaseRsp realTimeHistory(VideoVoiceListDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.realTimeHistory(query)
        ));
    }

    @GetMapping("/turn/lottery")
    public BaseRsp turnLottery(TurnSignUpDTO query){
        return analysisService.getTurnLottery(query);
    }

    @GetMapping("/turn/statistics/list")
    public BaseRsp statisticsList(TurnSignUpDTO query){
        return analysisService.statisticsList(query);
    }

    @PostMapping("/turn/applyItem")
    public BaseRsp turnApplyItem(@RequestBody TurnSignUpDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.getApplyItem(query)
        ));
    }

    @PostMapping("/turn/redPacketItem")
    public BaseRsp turnRedPaketItem(@RequestBody TurnSignUpDTO query){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.getRedPacketItem(query)
        ));
    }

    @GetMapping("/turn/redPacket")
    public BaseRsp turnRedPaket(TurnSignUpDTO query){
        return analysisService.getTurnRedPacket(query);
    }

    @GetMapping("/egg/records")
    public BaseRsp eggRecords(EggQueryDTO queryDTO){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.getEggRecords(queryDTO), "count", analysisService.getEggRecordsCount(queryDTO)
        ));
    }
    @GetMapping("/egg/single")
    public BaseRsp eggSingle(EggQueryDTO queryDTO){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.eggSingle(queryDTO)
        ));
    }

    @GetMapping("/egg/statistics")
    public BaseRsp eggStatistics(EggQueryDTO queryDTO){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.getEggStatistics(queryDTO), "count", analysisService.getEggStatisticsCount(queryDTO)
        ));
    }

    @GetMapping("/egg/analysis")
    public BaseRsp eggAnalysis(EggQueryDTO queryDTO){
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", analysisService.getEggAnalysisList(queryDTO), "count", analysisService.getEggAnalysisCount(queryDTO)
        ));
    }

    @GetMapping("/quickMatch/list")
    public BaseRsp quickMatchList(ChannelQueryDTO query) {
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("list", analysisService.quickMatchList(query),
                "count", analysisService.quickMatchCount(query)));
    }

    @GetMapping("/ipAddress")
    public BaseRsp getIpAddress(@RequestParam(value = "query", required = false) String query,
                                @RequestParam(value = "userId") String userId){
        Map<String, String> queryMap = new HashMap<>();
        if (query != null){
            queryMap.put("query", query);
        }
        queryMap.put("userId", userId);
        queryMap.put("resource_id", "5809");
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "data", analysisService.getIpAddress(queryMap)
        ));
    }
    @PostMapping("/insert/user/class")
    public BaseRsp insertUserClass(@RequestBody JSONObject params){
        analysisService.UserClassEdit(params);
        return new BaseRsp(ResultEnum.SUCCESS);
    }

    @PostMapping("/delete/user/class")
    public BaseRsp deleteUserClass(@RequestBody JSONObject params){
        analysisService.deleteUserClass(params);
        return new BaseRsp(ResultEnum.SUCCESS);
    }

    @PostMapping("/user/class/list")
    public BaseRsp userClassList(){
        List<UserClassifyDO> response = analysisService.userClassList();
        return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of(
                "list", response, "count", response.size()
        ));
    }

    /**
     * 注册用户分析.
     * @return
     */
    @RequestMapping(value = "/register/statistics", method = RequestMethod.GET)
    @RequiresPermissions("userInfo:view")
    public BaseDO registerStatistics(
            @RequestParam(value="offset", required = false, defaultValue="0") int offset,
            @RequestParam(value="limit", required=false, defaultValue="20") int pageSize,
            @RequestParam(value="appName", required=false) String username,
            @RequestParam(value="appChannel", required=false) String appChannel,
            @RequestParam(value="appVersion", required=false) String appVersion,
            @RequestParam(value="startTime", required=false) String startTime,
            @RequestParam(value="endTime", required=false) String endTime,
            @RequestParam(value="orderType", required=false, defaultValue="DESC") String orderType,
            @RequestParam(value="orderBy", required=false, defaultValue="updated_at") String orderBy
    ){
        JSONObject data = new JSONObject();
        int count = analysisService.getRegisterStatisticsCount(username, appChannel, appVersion, startTime, endTime);
        List<AccountRegisterStatistics> statisticsList = analysisService.getRegisterStatistics(offset, pageSize, username, appChannel, appVersion, startTime, endTime, orderBy, orderType);
        PageInfoDTO pageInfo = PageUtils.structurePageInfo(statisticsList, count, statisticsList.size(), offset, pageSize);
        return new BaseDO(pageInfo);
    }

    /**
     * 市场数据分析.
     * @return
     */
    @RequestMapping(value = "/market/statistics", method = RequestMethod.GET)
    @RequiresPermissions("userInfo:view")
    public BaseDO marketStatistics(
            @RequestParam(value="offset", required = false, defaultValue="0") int offset,
            @RequestParam(value="limit", required=false, defaultValue="20") int pageSize,
            @RequestParam(value="orderType", required=false, defaultValue="DESC") String orderType,
            @RequestParam(value="orderBy", required=false, defaultValue="updated_at") String orderBy
    ){
        JSONObject data = new JSONObject();
        int count = analysisService.getMarketStatisticsCount();
        List<MarketStatistics> statisticsList = analysisService.getMarketStatistics(offset, pageSize);
        PageInfoDTO pageInfo = PageUtils.structurePageInfo(statisticsList, count, statisticsList.size(), offset, pageSize);
        return new BaseDO(pageInfo);
    }

    @PutMapping("/market/extra")
    public BaseRsp marketExtraUpdate(@RequestBody MarketExtraDTO updateDTO) {
        analysisService.updateMarketExtra(updateDTO);
        return new BaseRsp(ResultEnum.SUCCESS);
    }

    /**
     * 获取quickbi临时凭据.
     * @return
     */
    @RequestMapping(value = "/access/ticket", method = RequestMethod.GET)
    public BaseRsp registerStatistics() {
        return new BaseRsp(ResultEnum.SUCCESS, analysisService.getQuickBiTicketData());
    }

    /**
     * 顾问整体数据.
     * @return
     */
    @RequestMapping(value = "/advisor/summary/statistics", method = RequestMethod.GET)
    @RequiresPermissions("userInfo:view")
    public BaseDO advisorSummaryStatistics(
            @RequestParam(value="offset", required = false, defaultValue="0") int offset,
            @RequestParam(value="limit", required=false, defaultValue="20") int pageSize,
            @RequestParam(value="orderType", required=false, defaultValue="DESC") String orderType,
            @RequestParam(value="orderBy", required=false, defaultValue="updated_at") String orderBy
    ) {
        JSONObject data = new JSONObject();
        int count = analysisService.getAdvisorSummaryStatisticsCount();
        List<AdvisorSummaryData> statisticsList = analysisService.getAdvisorSummaryStatistics(offset, pageSize);
        PageInfoDTO pageInfo = PageUtils.structurePageInfo(statisticsList, count, statisticsList.size(), offset, pageSize);
        return new BaseDO(pageInfo);
    }

    /**
     * 订单服务整体数据.
     * @return
     */
    @RequestMapping(value = "/order/summary/statistics", method = RequestMethod.GET)
    @RequiresPermissions("userInfo:view")
    public BaseDO orderSummaryStatistics(
            @RequestParam(value="offset", required = false, defaultValue="0") int offset,
            @RequestParam(value="limit", required=false, defaultValue="20") int pageSize,
            @RequestParam(value="type", required=false, defaultValue="1") int type,
            @RequestParam(value="orderType", required=false, defaultValue="DESC") String orderType,
            @RequestParam(value="orderBy", required=false, defaultValue="updated_at") String orderBy
    ) {
        JSONObject data = new JSONObject();
        List<Integer> types = new ArrayList<Integer>();

        if(type == 1) {
            //倾听订单
            types.add(12);
            types.add(13);
        } else if(type == 2) {
            //离线订单，占卜师实时订单
            types.add(9);
            types.add(4);
            types.add(5);
            types.add(6);
        } else if(type == 3) {
            // 仪式
            types.add(7);
        }
        long count = analysisService.getOrderSummaryStatisticsCount(types);
        List<OrderSummaryData> statisticsList = analysisService.getOrderSummaryStatistics(types, offset, pageSize);
        PageInfoDTO pageInfo = PageUtils.structurePageInfo(statisticsList, (int)count, statisticsList.size(), offset, pageSize);
        return new BaseDO(pageInfo);
    }
}